package com.mnc.dao.base;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


@Transactional
public class BaseDaoImpl implements IBaseDao{
	@PersistenceContext
	protected EntityManager entityManager;
	
	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}
	
	@Override
	public void add(Object eneity) {
		entityManager.persist(eneity);
	}

	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> T find(Class<T> eneityClass, Object eneityId) {
		return entityManager.find(eneityClass, eneityId);
	}

	@Override
	public <T> void remove(Class<T> eneityClass, Object eneityId) {
		this.remove(eneityClass, new Object[] { eneityId });
	}

	@Override
	public <T> void remove(Class<T> eneityClass, Object[] eneityIds) {
		for (Object id : eneityIds)
			entityManager.remove(entityManager.getReference(eneityClass, id));
	}

	@Override
	public void update(Object eneity) {
		entityManager.merge(eneity);
	}

	/**
	 * 获取实体的名称
	 * 
	 * @param <T>
	 * @param eneityClass
	 *            实体类
	 * @return
	 */
	protected <T> String getEntityName(Class<T> eneityClass) {
		String entityName = eneityClass.getSimpleName(); // 获取类的简单名称
		Entity entityClass = eneityClass.getAnnotation(Entity.class);
		if (null != entityClass.name() && !"".equals(entityClass.name()))
			entityName = entityClass.name();
		return entityName;
	}


	
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> long getCount(Class<T> eneityClass) {
		Query query = entityManager.createQuery("select count(o) from "
				+ this.getEntityName(eneityClass) + " o");
		Number singleResult = (Number) query.getSingleResult();
		return (long)singleResult.longValue();
	}

	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> long getCount(Class<T> eneityClass, String where, Object[] params) {
		Query query = entityManager.createQuery("select count(o) from "
				+ this.getEntityName(eneityClass) + " o where " + where);
		if (params != null && params.length > 0)
			for (int i = 0; i < params.length; i++)
				query.setParameter(i + 1, params[i]);
		Number singleResult = (Number) query.getSingleResult();
		return (long)singleResult.longValue();
	}

	@Override
	public <T> Boolean checkExist(Class<T> eneityClass, String where,
			Object[] params) {
		if (this.getCount(eneityClass, where, params) > 0)
			return true;
		return false;
	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> List<T> getData(Class<T> eneityClass) {
		List<T> tlist = new ArrayList<T>();
		String entityName = this.getEntityName(eneityClass);
		Query query = entityManager.createQuery("FROM " + entityName);
		tlist=query.getResultList();
		return tlist;
	}

	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> List<T> getDateList(Class<T> eneityClass) {
		return this.getData(eneityClass);

	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> List<T> getData(Class<T> eneityClass, String where,
			Object[] params) {
		List<T> tlist = new ArrayList<T>();
		String entityName = this.getEntityName(eneityClass);

		Query query = entityManager.createQuery("select o from " + entityName
				+ " o where " + where);
		if (params != null && params.length > 0)
			for (int i = 0; i < params.length; i++)
				query.setParameter(i + 1, params[i]);

		tlist=query.getResultList();
		return tlist;
	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> List<T> getData(Class<T> eneityClass,
			String[] returnFileds, String where, Object[] params) {

		List<T> tlist = new ArrayList<T>();
		String entityName = this.getEntityName(eneityClass);
		StringBuffer filedBuffer = new StringBuffer();

		for (int i = 0; i < returnFileds.length; i++) {
			filedBuffer.append("o." + returnFileds[i] + ",");
		}
		filedBuffer.deleteCharAt(filedBuffer.length() - 1);
		Query query = entityManager.createQuery("select " + filedBuffer + " from "
				+ entityName + " o where " + where);
		if (params != null && params.length > 0)
			for (int i = 0; i < params.length; i++)
				query.setParameter(i + 1, params[i]);

		tlist=query.getResultList();
		return tlist;
	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> T getUnique(Class<T> eneityClass, String where, Object[] params) {
		String entityName = this.getEntityName(eneityClass);
		Query query = entityManager.createQuery("select o from " + entityName
				+ " o where " + where);
		if (params != null && params.length > 0)
			for (int i = 0; i < params.length; i++)
				query.setParameter(i + 1, params[i]);
		
		return (T)query.getSingleResult();
	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> List<T> getPageData(Class<T> eneityClass, String where,
			Object[] params, int first, int size) {
		List<T> tlist = new ArrayList<T>();
		String entityName = this.getEntityName(eneityClass);

		Query query = entityManager.createQuery("select o from " + entityName
				+ " o where " + where);
		if (params != null && params.length > 0)
			for (int i = 0; i < params.length; i++)
				query.setParameter(i + 1, params[i]);

		query.setFirstResult(first);
		query.setMaxResults(size);
		tlist=query.getResultList();
		return tlist;
	}
	
}
